#include <omp.h>
#include <unistd.h>

#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <stdexcept>
#include <thread>
#include <vector>
#include <dirent.h>
#include <sys/stat.h>

using namespace std;

const string kOutputDir = "./output";
const string lat_start = " lat=\"";
const string lon_start = "\" lon=\"";
const string lon_end = "\">";

void process_file(std::string this_path, std::string output_file) {
  ofstream ofs;
  ifstream ifs;
  ofs.open(output_file);
  if (ofs.fail()) {
    cout << "can't open file " << output_file << endl;
    std::abort();
  }

  cout << "opening: " << this_path << endl;
  cout << "saving to ->: " << output_file << endl;

  DIR *dirp;  //定义一个目录指针
  struct dirent* direntp;
  /* 打开目录，先判断一下, 注意opendir接收的是const char* 类型 */
  if ((dirp = opendir(this_path.c_str())) == NULL) {
    cout <<"in valid dir:" << this_path << endl;
    std::abort();
  }
  /* 没问题的话开始遍历dir */
  while ((direntp = readdir(dirp)) != NULL) {
    if (direntp->d_type == DT_REG) {
      char dirbuf[512];
      memset(dirbuf, 0, sizeof(dirbuf));
      strcpy(dirbuf, this_path.c_str());
      strcat(dirbuf, "/");
      strcat(dirbuf, direntp->d_name);  //此时dirbuf已经是完整路径了
      ifs.open(dirbuf);

      string line;
      while (getline(ifs, line)) {
        std::regex reg(".*<trkpt lat=.*lon=.*>.*");

        if (std::regex_match(line, reg)) {
          int i = line.find(lat_start);
          int j = line.find(lon_start);
          int k = line.find(lon_end);

          auto lat_i = i + lat_start.size();
          auto lat_str = line.substr(lat_i, j - lat_i);

          auto lon_i = j + lon_start.size();
          auto lon_str = line.substr(lon_i, k - lon_i);

          ofs << lat_str << " " << lon_str << endl;
        }
      }

      ifs.close();
    } else {
      cout << "error file..." << endl;
      std::abort();
    }
  }
  ofs.close();
}

void process(std::string path, std::string output) {
  /* 同样，打开前先判断 */
  DIR* dirp;
  struct dirent* direntp;
  if ((dirp = opendir(path.c_str())) == NULL) {
    cout << "in valid dir:" << path << endl;
    std::abort();
  }
  vector<std::string> all_path;
  while ((direntp = readdir(dirp)) != NULL) {
    if (direntp->d_type == DT_DIR) {
      all_path.push_back(direntp->d_name);
    } else {
      cout << "error 2nd level directory..." << endl;
      std::abort();
    }
  }

  int n = all_path.size();

#pragma omp parallel for
  for (int i = 0; i < n; ++i) {
    auto this_path = all_path[i];
    auto this_output = output;
    this_output.append(output + this_path + ".txt");

    process_file(this_path, this_output);
  }
}

int main(int argc, char* argv[]) {
  if (argc < 2) {
    cout << "Enter the base directory..." << endl;
    std::abort();
  }

  string base_path = argv[1];
  auto dir = opendir(base_path.c_str());
  if (dir == NULL) {
    cout << "error base directory" << endl;
    std::abort();
  }

  dir = opendir(kOutputDir.c_str());
  if (dir == NULL) {
    mkdir(kOutputDir.c_str(), ACCESSPERMS);
  }

  char outdirbuf[512];

  DIR *dirp;  //定义一个目录指针
  struct dirent* direntp;
  if ((dirp = opendir(base_path.c_str())) == NULL) {
    cout << "in valid dir:" << base_path << endl;
    std::abort();
  }

  while ((direntp = readdir(dirp)) != NULL) {
    if (direntp->d_type == DT_DIR) {
      char dirbuf[512];
      memset(dirbuf, 0, sizeof(dirbuf));
      strcpy(dirbuf, kOutputDir.c_str());
      strcat(dirbuf, "/");
      strcat(dirbuf, direntp->d_name);  //此时dirbuf已经是完整路径了

      auto dir = opendir(dirbuf);
      if (dir == NULL) {
        mkdir(kOutputDir.c_str(), ACCESSPERMS);
      }

      process(direntp->d_name, dirbuf);
    } else {
      cout << "Error 1st level directory..." << endl;
      std::abort();
    }
  }

  return 0;
}